package pooller.repository;

import jakarta.mail.Address;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import jakarta.persistence.EntityManager;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.Email;
import pooller.AbstractEntityRemoteServiceServlet;
import pooller.MailServletResponse;
import pooller.PoolingSurviveService;
import pooller.dto.pool.PoolMetaInfoDto;
import pooller.dto.uac.CabinetDto;
import pooller.model.pool.PoolMainInfo;
import pooller.model.uac.Invitation;

import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;

public class PoolingSurviveServiceIml extends AbstractEntityRemoteServiceServlet implements PoolingSurviveService {
    @Override
    public CabinetDto invite(PoolMetaInfoDto pool, @Email String email) {
        if (pool == null || pool.getId() == null) {
            throw new Error("Pool is null");
        }
        EntityManager em = emf.createEntityManager();
        PoolMainInfo poolMainInfo = em.find(PoolMainInfo.class, pool.getId());
        if (poolMainInfo == null) {
            em.close();
            throw new Error("Pool not found " + pool.getId());
        }
        em.getTransaction().begin();
        Invitation invitation = new Invitation();
        invitation.setEmail(email);
        invitation.setCreated(Timestamp.valueOf(LocalDateTime.now()));
        invitation.setPool(poolMainInfo);
        try {
            em.persist(invitation);
            HttpServletRequest threadLocalRequest = getThreadLocalRequest();
            threadLocalRequest.setAttribute("invitation", invitation);
            threadLocalRequest.setAttribute("pool", pool);
            sendMessage(email, "/templates/email/invite.jsp");
        } catch (IOException | ServletException | MessagingException e) {
            em.getTransaction().rollback();
            log("send message", e);
            throw new Error("send message", e);
        } finally {
            em.getTransaction().commit();
            em.close();
        }
        CabinetDto cabinetDto = new CabinetDto();
        cabinetDto.setEmail(email);
        cabinetDto.setId(String.valueOf(invitation.getId()));
        return cabinetDto;
    }

    void sendMessage(String email, String jsp) throws MessagingException, ServletException, IOException {
        MimeMessage message = new MimeMessage(session);
        InternetAddress internetAddress = new InternetAddress(email);
        message.setRecipients(Message.RecipientType.TO, new Address[]{internetAddress});

        HttpServletRequest threadLocalRequest = getThreadLocalRequest();
        MailServletResponse msr = new MailServletResponse();

        threadLocalRequest
                .getRequestDispatcher(jsp)
                .forward(threadLocalRequest, msr);

        message.setSubject(msr.getHeader("subject"));
        message.setContent(msr.toString(), msr.getContentType());
        message.saveChanges();
        Transport smtp = session.getTransport("smtp");
        smtp.connect();
        smtp.sendMessage(message, new Address[]{internetAddress});
    }

    @Override
    public void register(String email) {
        try {
            sendMessage(email, "/templates/email/registration.jsp");
        } catch (IOException| ServletException| MessagingException e) {
            log("send message", e);
            throw new Error("send message", e);
        }
    }
}
